#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;

const int MAX = 200200;
int H, W;
vector<int> A[MAX];
vector<long long> f[MAX];
int P[MAX];
// 检查函数：判断给定初始值x是否能够从网格左上角到达右下角
// 参数x: 初始能量值
// 返回值: 如果能够到达右下角且能量非负，返回true；否则返回false
bool check(long long x) {
  // 初始化动态规划数组f，表示到达每个位置时的最大能量值
  // 初始化为负无穷大，表示不可达状态
  for (int i = 1; i <= H; ++i)
    for (int j = 1; j <= W; ++j)
      f[i][j] = -1e18;

  // 起点(1,1)的初始能量为x
  f[1][1] = x;

  // 动态规划遍历整个网格
  for (int i = 1; i <= H; ++i) {
    for (int j = 1; j <= W; ++j) {
      // 计算当前位置的曼哈顿距离（从起点到当前位置的步数）
      int d = i + j - 1;

      // 到达当前位置时，加上该位置的收益A[i][j]
      f[i][j] += A[i][j];
      // 减去第d步的代价P[d]
      f[i][j] -= P[d];

      // 如果当前位置能量非负（表示可以继续前进）
      if (f[i][j] >= 0) {
        // 如果可以向下移动，更新下方格子的最大能量值
        if (i + 1 <= H)
          f[i + 1][j] = max(f[i + 1][j], f[i][j]);
        // 如果可以向右移动，更新右方格子的最大能量值
        if (j + 1 <= W)
          f[i][j + 1] = max(f[i][j + 1], f[i][j]);
      }
    }
  }

  // 检查是否能够到达终点(H,W)且能量非负
  return f[H][W] >= 0;
}

int main() {

  cin >> H >> W;
  for (int i = 1; i <= H; ++i) {
    A[i].resize(W + 1);
    f[i].resize(W + 1);
    for (int j = 1; j <= W; ++j)
      cin >> A[i][j];
  }

  for (int i = 1; i < H + W; ++i)
    cin >> P[i];
  long long L = 0, R = 1e16, ret;
  while (L <= R) {
    long long mid = (L + R) >> 1;
    if (check(mid))
      ret = mid, R = mid - 1;
    else
      L = mid + 1;
  }

  cout << ret << endl;
  return 0;
}